package vashion.azeroth.core.service.tran.impl;

import java.util.Date;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import vashion.azeroth.common.common.check.FormatCheck;
import vashion.azeroth.common.push.util.JPushAlertUtils;
import vashion.azeroth.contant.AzerothConstants;
import vashion.azeroth.contant.NeteaseSMSTemplateEnum;
import vashion.azeroth.contant.PushAlertEnum;
import vashion.azeroth.contant.TranErrorEnum;
import vashion.azeroth.core.manager.item.BaseItemSkuManager;
import vashion.azeroth.core.manager.personal.tran.PersonalDisburseManager;
import vashion.azeroth.core.manager.personal.tran.PersonalRechargeOrderManager;
import vashion.azeroth.core.manager.personal.tran.PersonalSnapshotManager;
import vashion.azeroth.core.manager.personal.tran.PersonalTranDetailManager;
import vashion.azeroth.core.manager.personal.tran.PersonalVAccountManager;
import vashion.azeroth.core.personal.pojo.PersonalMember;
import vashion.azeroth.core.personal.tran.pojo.PersonalDisburse;
import vashion.azeroth.core.personal.tran.pojo.PersonalRechargeOrder;
import vashion.azeroth.core.personal.tran.pojo.PersonalSnapshotSku;
import vashion.azeroth.core.personal.tran.pojo.PersonalTranDetail;
import vashion.azeroth.core.personal.tran.pojo.PersonalVAccount;
import vashion.azeroth.core.result.ApiResult;
import vashion.azeroth.core.service.impl.PersonalMemberServiceImpl;
import vashion.azeroth.core.service.tran.PingCallbackService;
import vashion.azeroth.core.sms.NeteaseSMSSender;
import vashion.azeroth.task.job.PushJob;
import vashion.azeroth.task.job.SmsJob;
import vashion.azeroth.task.util.AsyncTaskExecutor;

import com.alibaba.fastjson.JSON;
import com.pingplusplus.model.Charge;
import com.pingplusplus.model.Refund;

@Service
public class PingCallbackServiceImpl implements PingCallbackService {
	
	private final static Logger log = LoggerFactory.getLogger(PingCallbackServiceImpl.class);
	
	@Autowired
	private PersonalRechargeOrderManager rechargeOrderManager;
	@Autowired
	private PersonalVAccountManager vaccountManager;
	@Autowired
	private PersonalTranDetailManager tranDetailManager;
	@Autowired
	private PersonalDisburseManager disburseManager;
	@Autowired
	private BaseItemSkuManager baseItemSkuManager;
	@Autowired
	private PersonalSnapshotManager snapshotManager;
	@Autowired
	private PersonalMemberServiceImpl memberService;
	@Autowired
	private NeteaseSMSSender smsSender;
	
	@Override
	public void rebundCallback(Refund refund) {
		
	}

	/**
	 * 先执行充值回调流程，如果充值订单中消费订单号不为空，刚执行购买流程
	 */
	@Transactional
	@Override
	public void rechargeCallback(Charge charge) {
		
		PersonalRechargeOrder rechargeOrder = rechargeOrderManager.getRechargeOrderByRechargeOrderNoWithLock(charge.getOrderNo());
		
		if(null == rechargeOrder) {
			if(log.isInfoEnabled()) {
				log.info("充值订单不存在,回调订单号=" + charge.getOrderNo());
			}
		}
		
		if(rechargeOrder.getStatus() != 0) {
			if(log.isInfoEnabled()) {
				log.info("充值订单状态不正确,目前状态为=" + rechargeOrder.getStatus());
			}
			return;
		}
		
//		if(rechargeOrder.getAmount() != Long.valueOf(charge.getAmount())) {
//			if(log.isInfoEnabled()) {
//				log.info("回调金额与充值金额不一致,回调金额为=" + rechargeOrder.getStatus());
//			}
//			return;
//		}
		
		//处理充值账户明细与余额
		PersonalVAccount vaccount = vaccountManager.getByMemberId(rechargeOrder.getMemberId());
		tranDetailManager.save(buildTranDetail(vaccount, rechargeOrder));
		
		if(null == vaccount) {
			vaccountManager.save(buildVAccount(vaccount, rechargeOrder));
		} else {
			vaccountManager.update(buildVAccount(vaccount, rechargeOrder));
		}
		
		rechargeOrderManager.update(buildRechargeOrder(rechargeOrder, charge, AzerothConstants.PersonalRechargeOrder.RechargeType.recharged));
		
		//消费订单号不为空,走消费流程
		if(!StringUtils.isBlank(rechargeOrder.getDisburseNo())) {
			PersonalDisburse disburse = disburseManager.getByDisburseNo(rechargeOrder.getDisburseNo());
			
			if(null != disburse) {
				disburse.setStatus(AzerothConstants.PersonalDisburse.DisburseStatus.agent_payment);
				disburse.setTimeEdit(new Date());
				disburseManager.update(disburse);
			}
			
			//买家付款给卖家
			PersonalVAccount sellerVaccount = vaccountManager.getByMemberId(disburse.getSellerMemberId());
			tranDetailManager.save(buildSellerTranDetail(sellerVaccount, disburse));
			
			if(null == sellerVaccount) {
				vaccountManager.save(buildSellerVAccount(sellerVaccount, disburse));
			} else {
				vaccountManager.update(buildSellerVAccount(sellerVaccount, disburse));
			}
			
			PersonalVAccount buyerVaccount = vaccountManager.getByMemberId(disburse.getBuyerMemberId());
			
			tranDetailManager.save(buildBuyerTranDetail(buyerVaccount, disburse));
			//代理商账户在充值回调时已创建，不需要判空
			vaccountManager.update(buildBuyerVAccount(buyerVaccount, disburse));
			
			PersonalMember buyerMember = memberService.get(disburse.getBuyerMemberId());
			PersonalMember sellerMember = memberService.get(disburse.getSellerMemberId());
			
			if(null != sellerMember.getMobilePhone() && FormatCheck.isMobile(sellerMember.getMobilePhone())) {
				SmsJob job = new SmsJob(smsSender, sellerMember.getMobilePhone(), NeteaseSMSTemplateEnum.DISBUSE_ACCEPTED.getName(), buyerMember.getNickName());
				AsyncTaskExecutor.submit(job);
			}

			PushJob job = new PushJob(sellerMember.getRegistrationId(), JPushAlertUtils.getAlertMsgReplace(PushAlertEnum.PUSH_AGENT_PAYMENT.getAlertMsg(), buyerMember.getNickName(), rechargeOrder.getDisburseNo()));
			AsyncTaskExecutor.submit(job);
		}
		
	}
	
	@Transactional
	@Override
	public ApiResult<String> confirmPayed(String disburseNo, String refuseReason) {
		
        PersonalDisburse disburse = disburseManager.getByDisburseNo(disburseNo);
        
        PersonalMember buyerMember = memberService.get(disburse.getBuyerMemberId());
		PersonalMember sellerMember = memberService.get(disburse.getSellerMemberId());
    	
    	if(disburse.getStatus() != AzerothConstants.PersonalDisburse.DisburseStatus.certificate_uploaded) {
    		return ApiResult.newErrorResult(TranErrorEnum.DISBURSE_ORDER_STATUS_ERROR.getErrorCode(), "订单" + TranErrorEnum.DISBURSE_ORDER_STATUS_ERROR.getErrorMessage());
    	}
    	
    	if(null != refuseReason) {
    		disburse.setStatus(AzerothConstants.PersonalDisburse.DisburseStatus.confirm_refuse);
    		disburse.setRefuseReason(refuseReason);
    		disburse.setTimeEdit(new Date());
    		disburseManager.update(disburse);
    		
    		if(null != buyerMember.getMemberName() && FormatCheck.isMobile(buyerMember.getMemberName())) {
				SmsJob job = new SmsJob(smsSender, buyerMember.getMemberName(), NeteaseSMSTemplateEnum.DISBUSE_REJECTED.getName(), "vashion");
	    		AsyncTaskExecutor.submit(job);
			}

    		PushJob job = new PushJob(buyerMember.getRegistrationId(), JPushAlertUtils.getAlertMsgReplace(PushAlertEnum.PUSH_CERTIFICATE_REFUSE.getAlertMsg(), "vashion", disburse.getDisburseNo()));
    		AsyncTaskExecutor.submit(job);
    		
    		return ApiResult.newSuccessResult();
    	} else {
    		disburse.setStatus(AzerothConstants.PersonalDisburse.DisburseStatus.agent_payment);
    		disburse.setTimeEdit(new Date());
    		disburseManager.update(disburse);
    		
    		if(null != sellerMember.getMobilePhone() && FormatCheck.isMobile(sellerMember.getMobilePhone())) {
				SmsJob job = new SmsJob(smsSender, sellerMember.getMobilePhone(), NeteaseSMSTemplateEnum.DISBUSE_ACCEPTED.getName(), buyerMember.getNickName());
	    		AsyncTaskExecutor.submit(job);
			}

    		PushJob job = new PushJob(sellerMember.getRegistrationId(), JPushAlertUtils.getAlertMsgReplace(PushAlertEnum.PUSH_AGENT_PAYMENT.getAlertMsg(), buyerMember.getNickName(), disburse.getDisburseNo()));
    		AsyncTaskExecutor.submit(job);
    	}
    	
		//处理充值账户明细与余额
		PersonalVAccount vaccount = vaccountManager.getByMemberId(disburse.getBuyerMemberId());
		
		PersonalRechargeOrder rechargeOrder = new PersonalRechargeOrder();
		rechargeOrder.setMemberId(disburse.getBuyerMemberId());
		rechargeOrder.setMemberName(disburse.getBuyerMemberName());
		rechargeOrder.setAmount(disburse.getTotalPrice());
		
		if(null == vaccount) {
			vaccountManager.save(buildVAccount(vaccount, rechargeOrder));
		} else {
			vaccountManager.update(buildVAccount(vaccount, rechargeOrder));
		}
		
		disburse.setSkus(JSON.parseArray(disburse.getSnapshot().getProductQuantity(), PersonalSnapshotSku.class));
		
		//减商品库存
		for (PersonalSnapshotSku sku : disburse.getSkus()) {
			if(!baseItemSkuManager.updateItemSkuNum(sku.getId(), sku.getStock(), Boolean.FALSE)) {
				log.error("商品库存不足,商品ID:" + sku.getId() + ", skuId:" + sku.getId() + ", 购买数量:" + sku.getStock());
			}
		}
		
		//买家付款给卖家
		PersonalVAccount sellerVaccount = vaccountManager.getByMemberId(disburse.getSellerMemberId());
		tranDetailManager.save(buildSellerTranDetail(sellerVaccount, disburse));
		
		if(null == sellerVaccount) {
			vaccountManager.save(buildSellerVAccount(sellerVaccount, disburse));
		} else {
			vaccountManager.update(buildSellerVAccount(sellerVaccount, disburse));
		}
		
		PersonalVAccount buyerVaccount = vaccountManager.getByMemberId(disburse.getBuyerMemberId());
		
		tranDetailManager.save(buildBuyerTranDetail(buyerVaccount, disburse));
		//代理商账户在充值回调时已创建，不需要判空
		vaccountManager.update(buildBuyerVAccount(buyerVaccount, disburse));
		
		return ApiResult.newSuccessResult();
	}
	
	
	private PersonalTranDetail buildTranDetail(PersonalVAccount account, PersonalRechargeOrder rechargeOrder) {
		PersonalTranDetail tranDetail = new PersonalTranDetail();
		tranDetail.setMemberId(rechargeOrder.getMemberId());
		tranDetail.setMemberName(rechargeOrder.getMemberName());
		tranDetail.setIncome(rechargeOrder.getAmount());
		tranDetail.setPayout(0);
		tranDetail.setPreBalance(null == account?0:account.getUseableBalance());
		tranDetail.setCurBalance(null == account?rechargeOrder.getAmount():account.getUseableBalance()+rechargeOrder.getAmount());
		tranDetail.setTranNo(rechargeOrder.getRechargeOrderNo());
		tranDetail.setTranType(AzerothConstants.PersonalTranDetail.TranDetailStatus.recharge);
		tranDetail.setTimeAdd(new Date());
		tranDetail.setRemark("充值");
		
		return tranDetail;
	}
	
	private PersonalTranDetail buildBuyerTranDetail(PersonalVAccount account, PersonalDisburse disburse) {
		PersonalTranDetail tranDetail = new PersonalTranDetail();
		tranDetail.setMemberId(disburse.getBuyerMemberId());
		tranDetail.setMemberName(disburse.getBuyerMemberName());
		tranDetail.setIncome(0);
		tranDetail.setPayout(disburse.getTotalPrice());
		tranDetail.setPreBalance(account.getUseableBalance());
		tranDetail.setCurBalance(account.getUseableBalance()-disburse.getTotalPrice());
		tranDetail.setTranNo(disburse.getDisburseNo());
		tranDetail.setTranType(AzerothConstants.PersonalTranDetail.TranDetailStatus.disburse);
		tranDetail.setTimeAdd(new Date());
		tranDetail.setRemark("消费");
		
		return tranDetail;
	}
	
	private PersonalTranDetail buildSellerTranDetail(PersonalVAccount account, PersonalDisburse disburse) {
		PersonalTranDetail tranDetail = new PersonalTranDetail();
		tranDetail.setMemberId(disburse.getSellerMemberId());
		tranDetail.setMemberName(disburse.getSellerMemberName());
		tranDetail.setIncome(disburse.getTotalPrice());
		tranDetail.setPayout(0);
		tranDetail.setPreBalance(null == account?0:account.getUseableBalance());
		tranDetail.setCurBalance(null == account?disburse.getTotalPrice():account.getUseableBalance()+disburse.getTotalPrice());
		tranDetail.setTranNo(disburse.getDisburseNo());
		tranDetail.setTranType(AzerothConstants.PersonalTranDetail.TranDetailStatus.Transfer);
		tranDetail.setTimeAdd(new Date());
		tranDetail.setRemark("代理商转账");
		
		return tranDetail;
	}
	
	private PersonalVAccount buildVAccount(PersonalVAccount account, PersonalRechargeOrder rechargeOrder) {
		if(null == account) {
			account = new PersonalVAccount();
			account.setMemberId(rechargeOrder.getMemberId());
			account.setMemberName(rechargeOrder.getMemberName());
			account.setTotalBalance(rechargeOrder.getAmount());
			account.setUseableBalance(rechargeOrder.getAmount());
			account.setFreezeBalance(0);
			account.setTimeAdd(new Date());
			account.setTimeEdit(new Date());
		} else {
			account.setTotalBalance(account.getTotalBalance() + rechargeOrder.getAmount());
			account.setUseableBalance(account.getUseableBalance()  + rechargeOrder.getAmount());
			account.setTimeEdit(new Date());
		}
		
		return account;
	}
	
	private PersonalVAccount buildBuyerVAccount(PersonalVAccount account, PersonalDisburse disburse) {
		account.setTotalBalance(account.getTotalBalance() - disburse.getTotalPrice());
		account.setUseableBalance(account.getUseableBalance() - disburse.getTotalPrice());
		account.setTimeEdit(new Date());
		return account;
	}
	
	private PersonalVAccount buildSellerVAccount(PersonalVAccount account, PersonalDisburse disburse) {
		if(null == account) {
			account = new PersonalVAccount();
			account.setMemberId(disburse.getSellerMemberId());
			account.setMemberName(disburse.getSellerMemberName());
			account.setTotalBalance(disburse.getTotalPrice());
			account.setUseableBalance(disburse.getTotalPrice());
			account.setFreezeBalance(0);
			account.setTimeAdd(new Date());
			account.setTimeEdit(new Date());
		} else {
			account.setTotalBalance(account.getTotalBalance() + disburse.getTotalPrice());
			account.setUseableBalance(account.getUseableBalance()  + disburse.getTotalPrice());
			account.setTimeEdit(new Date());
		}
		
		return account;
	}
	
	private PersonalRechargeOrder buildRechargeOrder(PersonalRechargeOrder order, Charge charge, Integer type) {
		order.setStatus(AzerothConstants.PersonalRechargeOrder.RechargeOrderStatus.success);
		order.setOutOrderNo(charge.getTransactionNo());
		order.setPingxxId(charge.getId());
		order.setRechargeType(type);
		order.setTimeFinished(new Date());
		return order;
	}

}
